home *** CD-ROM | disk | FTP | other *** search
- /* ==========================================================================================
-
- C FILE: MessageRoutines.c
-
- COPYRIGHT: (c) 1992-1994 Apple Computer Inc.
- All rights reserved.
-
- PURPOSE: This file contains routines which the HPXL driver uses to override
- some of the universal and vector specific messages. The file is partitioned
- into a section for utitlity routines, universal message override routines,
- and vector specific, message override routines.
-
- HISTORY: Date By Description
- ----- --- ----------------------------------
- 1/20/92 Harita Initial release
- 12/20/93 dmh Sync'd up for GX 1.0b3.
- 8/28/94 dmh Sync'd up for GX 1.0.1.
- 6/14/96 cn Updated to support Universal Interfaces 2.1.
-
- ========================================================================================== */
-
- #include <stdio.h>
- #include <Types.h>
- #include <OSUtils.h>
- #include <Memory.h>
- #include <ToolUtils.h>
- #include <Errors.h>
- #include <FixMath.h>
-
- #include <GXTypes.h>
- #include <GXErrors.h>
- #include <GXGraphics.h>
- #include <GXMath.h>
-
- #include <GXMessages.h>
- #include <GXPrinting.h>
- #include <GXPrinterDrivers.h>
-
- #include "ResourceDefines.h"
- #include "GlobalsDefs.h"
- #include "PackageRoutines.h"
-
- extern long A5Size (void);
- extern void A5Init (void *);
-
-
- SpecDrvrGlobals gGlobals;
-
-
- /* ============================ UNIVERSAL MESSAGE OVERRIDE ROUTINES ============================ */
-
- /* ======= SD_Initialize =======
-
- The Initalize message is issued when a client uses the NewJob function to create a
- new message chain to perform a job-oriented task. SD_Initialize initializes
- the globals of the HPGL driver.
- */
- OSErr SD_Initialize(void) // (in) not used on entry; this routine allocates the handle
- {
-
- OSErr anErr = noErr;
-
- anErr = NewMessageGlobals(A5Size(), A5Init);
- /* initialize globals */
- gGlobals.penWidth = 0;
-
- return(anErr);
-
- }
- /* SD_Initialize */
-
-
- /* ======= SD_ShutDown =======
-
- The ShutDown message is issued after the completion of a job oriented task and the
- message chain is being destroyed. SD_ShutDown deallocates the HPXL drivers globals.
- */
- OSErr SD_ShutDown(void)
- {
- /* dispose off globals */
- DisposeMessageGlobals();
- return(noErr);
- }
- /* SD_ShutDown */
-
-
- /* ======= SD_DefaultPrinter =======
-
- The DefaultPrinter message is issued when NewJob is called to create a new default printer
- object for some job. SD_DefaultPrinter creates a new ViewDevice which represents
- the specific features of the target device (e.g. color info., number of pens, etc.). It
- attaches the new ViewDevice to the job. The new ViewDevice is added so that the client
- application can determine specific settings about the device (e.g. in case it wants to constrain
- choices the user can make).
- */
- OSErr SD_DefaultPrinter( // (out) error code
- gxPrinter thePrinter) // (in) reference to the printer object being defaulted
- {
-
- OSErr anErr = noErr;
- gxViewDevice vd;
- gxGraphicsError stickyErr;
-
- /* Allow the other view devices to be set up before we add ours */
- anErr = Forward_GXDefaultPrinter(thePrinter);
- if (anErr != noErr)
- return(anErr);
-
- /* Create a new view device to represent the characteristics of the plotter. To do this */
- /* we need to create a fake bitmap. */
- {
- gxShape tempBitmap;
- gxBitmap aBitmap;
-
- aBitmap.pixelSize = 1;
- aBitmap.rowBytes = 0;
- aBitmap.width = 0;
- aBitmap.height = 0;
- aBitmap.image = (char*)gxMissingImagePointer;
- aBitmap.space = gxNoSpace;
- aBitmap.set = nil;
- aBitmap.profile = nil;
-
- tempBitmap = GXNewBitmap(&aBitmap, nil);
- if (tempBitmap == nil)
- return(GXGetGraphicsError(&stickyErr));
-
- vd = GXNewViewDevice(gxScreenViewDevices, tempBitmap);
- GXDisposeShape(tempBitmap);
-
- if (vd == nil)
- return(GXGetGraphicsError(&stickyErr));
- }
-
- /* Set the View Device Mapping to be identity -- render at 72 dpi */
- {
- gxMapping vdMapping;
-
- ResetMapping(&vdMapping);
- GXSetViewDeviceMapping(vd, &vdMapping);
- }
-
- /* Add the view device to the printer object */
- anErr = GXAddPrinterViewDevice(thePrinter, vd);
- if (anErr != noErr) goto CantAddPrinterVD;
-
- return(anErr);
-
- /******* Cleanup *******/
-
- CantAddPrinterVD:
-
- GXDisposeViewDevice(vd);
- return(anErr);
-
- }
- /* SD_DefaultPrinter */
-
-
- /* ======= SD_StartSendPage =======
-
- The StartSendPage message is issued when ImagePage is getting ready to render the next document
- page. SD_StartSendPage uses this signal to do three functions: 1) change the device transformation
- of the Vector IE will use so that Graphics coordinates are properly mapped to plotter coordinates;
- 2) check to see if it's a manual feed job, and if so, prompt the user to place the next
- sheet of paper in the printer; otherwise, issue a command to advance the paper; and 3) send an
- initialization command to the plotter.
- */
- OSErr SD_StartSendPage( // (out) error code
- gxFormat pageFormat) // (in) format of the page we will print
- {
-
- OSErr anErr = noErr;
- gxGraphicsError stickyErr;
- gxVectorImageDataHdl hImageData;
- gxTrayFeedInfo trayFeedInfo;
- long itemSize = sizeof(trayFeedInfo);
-
-
- /* First make sure all pending I/O has completed so that everything prints on the current page. */
- anErr = Send_GXWriteData(nil, 0);
- if (anErr != noErr) return (anErr);
-
- /* Next, change the device transformation so IE will translate the page's coordinates properly */
- {
- gxTransform theTransform;
- gxMapping theMapping;
-
- hImageData = gGlobals.hImageData;
-
- /* If a current device transform exists, kill it now */
- if ((*hImageData)->devTransform != nil)
- {
- GXDisposeTransform((*hImageData)->devTransform);
- (*hImageData)->devTransform = nil;
- }
-
- ResetMapping(&theMapping);
-
- /* This mapping causes the coordinates (x,y) to flip so they become (y,x) */
- theMapping.map[0][0] = 0x00000000;
- theMapping.map[1][1] = 0x00000000;
- theMapping.map[0][1] = 0x00010000;
- theMapping.map[1][0] = 0x00010000;
-
- theTransform = GXNewTransform();
- if (theTransform == nil)
- return(GXGetGraphicsError(&stickyErr));
-
- GXSetTransformMapping(theTransform, &theMapping);
- (*hImageData)->devTransform = theTransform;
- }
-
- /* Now check to see if it's a manual feed page. If so, display a dialog prompting the user to */
- /* place paper into the plotter; otherwise, issue a command to the device to feed the paper. */
-
- anErr = GetCollectionItem (GXGetJobCollection( GXGetJob() ),
- gxTrayFeedTag,
- gxPrintingTagID,
- &itemSize,
- &trayFeedInfo );
-
- if (trayFeedInfo.manualFeedThisPage) // T --> manual feed job;
- {
- gxStatusRecord *pStatus;
-
- pStatus = (gxStatusRecord*) NewPtr( sizeof(gxStatusRecord) + sizeof(short) );
- if (pStatus == nil)
- {
- anErr = MemError();
- goto CantMakeStatusRecord;
- }
-
- /* Fill in the status record appropriately */
- pStatus->statusOwner = 'drvr';
- pStatus->statResId = kUserAttentionID;
- pStatus->statResIndex = 1; //kManualFeedStatus;
- pStatus->dialogResult = 0;
- pStatus->bufferLen = 0;
- /* Continue alerting the user until he responds */
- do
- {
- anErr = GXAlertTheUser(pStatus);
-
- /* Note that we can't tell when the user places paper in the plotter */
- }
- while ((anErr == noErr) && (pStatus->dialogResult == 0));
-
- /* Examine the user's response to know whether to continue or cancel */
- switch ( *( (short *) (&pStatus->statusBuffer[0])) )
- {
- case ok: // Assume the paper is loaded
- anErr = noErr;
- break;
-
- case cancel: // User wants to terminate the job
- anErr = gxPrUserAbortErr;
- break;
- }
-
- /* Dump the temporary status record */
- DisposPtr((Ptr) pStatus);
-
- if (anErr != noErr) goto UserWantsToStop;
-
- /* Update the device's status */
- GXReportStatus(kUserAttentionID, kPrintingStatus);
- }
-
- /* Send out the start page HPGL2 commands to the device */
- anErr = StartOfPagePlot();
- if (anErr != noErr) goto CantDoStartOfPageCmnd;
-
- /* Pass the StartSendPage message on to the next person in the message chain */
- anErr = Forward_GXStartSendPage(pageFormat);
- if (anErr != noErr) goto CantSendStartPage;
-
- return(anErr);
-
- /******* Cleanup *******/
-
- CantSendStartPage:
- CantDoStartOfPageCmnd:
- UserWantsToStop:
- CantMakeStatusRecord:
- CantFlushDataPageAdvance:
- CantAdvanceThePage:
- GXDisposeTransform((*hImageData)->devTransform);
- (*hImageData)->devTransform = nil;
-
- return(anErr);
- }
- /* SD_StartSendPage */
-
-
- /* ======= SD_FinishSendPage =======
-
- The FinishSendPage message is issued when ImagePage is getting finished rendering the current
- page. SD_FinishSendPage uses this signal to do three functions: 1) remove the device
- transformatiom so it won't inadvertantly affect the scaling, rotation, etc. the
- Vector IE is doing; 2) if the paper in the plotter is to be cut, now is the time to
- issue the cut command; and 3) force the pen to return to the carousel so the user can pull
- out the paper.
- */
- OSErr SD_FinishSendPage(void)
- {
-
- OSErr anErr = noErr;
- gxVectorImageDataHdl hImageData;
-
- /* Deallocate the existing device transform */
- hImageData = gGlobals.hImageData;
- if ((*hImageData)->devTransform != nil)
- {
- GXDisposeTransform((*hImageData)->devTransform);
- (*hImageData)->devTransform = nil;
- }
-
- /* end of plotting */
- anErr = EndOfPagePlot();
- if (anErr != noErr)
- return(anErr);
-
- /* First make sure all pending I/O has completed so that everything prints on the current page. */
- anErr = Send_GXWriteData(nil, 0);
- if (anErr != noErr)
- return(anErr);
-
-
- /* Pass the FinishSendPage message on to the next person in the message chain */
- anErr = Forward_GXFinishSendPage();
-
- return(anErr);
-
- }
- /* SD_FinishSendPage */
-
-
- /* ======= SD_SetupImageData =======
-
- The SetupImageData message is issued to allow the driver to initialize any constant data that
- is used for imaging the entire document. SD_SetupImageData initializes fields within the
- hImageData handle so that the Vector IE knows how to image the pages given the specific
- constraints of the device.
- */
- OSErr SD_SetupImageData( // (out) error code
- gxVectorImageDataHdl hImageData) // (in) handle to the Vector IE imaging specific information
- {
-
- OSErr anErr = noErr;
- gxVectorImageDataPtr pImageData;
- gxGraphicsError stickyErr;
- gxPenTableHdl hPenTable;
- gxColor theBkgrndColor;
- gxColorSet theColorSet;
- gxPenTableEntry *pPen;
-
-
- gGlobals.bufferSize = 0;
-
- {
- pImageData = *hImageData;
-
- pImageData->renderOptions = gxATransferMode | gxPenLessPlotter;
- pImageData->devRes = ff(1016); // HPGL/2 is 1016 dpi plotter
- pImageData->devTransform = GXNewTransform();
-
- /* Assign constant vector image data values */
- pImageData->shapeData.shapeOptions = 0;
- pImageData->shapeData.maxPolyPoints = 150; // don't send a polygon with number of points more than this.
- pImageData->shapeData.shapeError = 0x00004000; // 1/4 pixel at 72 dpi
- pImageData->shapeData.textSize = ff(24); // outline text below 24 point size
- pImageData->shapeData.frameSize = ff(1); // fill framed shapes; do not stroke them
-
- }
-
- /* Set up the background color for the device to be white */
- theBkgrndColor.space = gxRGBSpace;
- theBkgrndColor.profile = nil;
- theBkgrndColor.element.rgb.red = 0xffff;
- theBkgrndColor.element.rgb.green = 0xffff;
- theBkgrndColor.element.rgb.blue = 0xffff;
- theBkgrndColor.element.component[4] = 0; // must be initialized
-
- {
- /* Create a representation of the pen table */
- short numColors = 2;
- gxSetColor pSetOfColors[2];
- gxSetColor *pAColor;
-
- pAColor = &pSetOfColors[0];
- /* black color */
- pAColor->rgb.red = 0;
- pAColor->rgb.green = 0;
- pAColor->rgb.blue = 0;
- ++pAColor;
- pAColor->rgb.red = 0xffff;
- pAColor->rgb.green = 0xffff;
- pAColor->rgb.blue = 0xffff;
-
- theColorSet = GXNewColorSet(gxRGBSpace, numColors, pSetOfColors);
- if (theColorSet == nil)
- {
- anErr = GXGetGraphicsError(&stickyErr);
- goto CantMakeColorSet;
- }
-
- /* Allocate space for the pen table we will return */
- hPenTable = (gxPenTableHdl) NewHandle( sizeof(gxPenTable) + (2 * sizeof(gxPenTableEntry)));
- if ((anErr = MemError()) != noErr) goto CantMakePenTable;
-
- (*hPenTable)->numPens = 2;
- pPen = &((*hPenTable)->pens[0]);
- BlockMove("\pBlack", &pPen->penName[0], 6);
- pPen->penPosition = 1;
- pPen->penColor.space = gxIndexedSpace;
- pPen->penColor.element.indexed.index = 1; // for black
- pPen->penUnits = 0; // device units i.e. 72dpi
- pPen->penThickness = 0x00008000; // half a pixel at 72 dpi
-
- pPen = &((*hPenTable)->pens[1]);
- BlockMove("\pWhite", &pPen->penName[0], 6);
- pPen->penPosition = 2;
- pPen->penColor.space = gxIndexedSpace;
- pPen->penColor.element.indexed.index = 2; // for white
- pPen->penUnits = 0; // device units i.e. 72dpi
- pPen->penThickness = 0x00008000; // half an inch at 72 dpi
-
- pImageData = *hImageData;
-
- pImageData->hPenTable = hPenTable;
- GXConvertColor(&theBkgrndColor, gxIndexedSpace, theColorSet, nil);
- pImageData->bgColor = theBkgrndColor;
- pImageData->clrSet = theColorSet;
-
- pImageData->halftoneInfo.halftoneSpace = gxNoSpace;
- pImageData->halftoneInfo.penIndexForBW = 1; // first pen
-
- }
-
- /* Remember the vector image data handle for later use during imaging */
- gGlobals.hImageData = hImageData;
-
- return(anErr);
-
- /******* Cleanup *******/
-
- CantMakePenTable:
- CantMakeColorSet:
-
- GXDisposeTransform((*hImageData)->devTransform);
- (*hImageData)->devTransform = nil;
- return(anErr);
-
- }
- /* SD_SetupImageData */
-
-
- /* ======= SD_CloseConnection =======
-
- The CloseConnection message is issued when the Printing Manager is closing the connection to the
- plotter. SD_CloseConnection uses this opportunity to dispose of the color set that the driver
- allocated and stored in the VectorImageData at SetupImageData time.
- */
- OSErr SD_CloseConnection(void) // (in) handle to the driver's globals
- {
-
- OSErr anErr = noErr;
- gxVectorImageDataHdl hImageData;
-
- hImageData = gGlobals.hImageData;
-
- /* Dispose of the Color Set if it was allocated */
- if ((*hImageData)->clrSet != nil)
- {
- GXDisposeColorSet((*hImageData)->clrSet);
- (*hImageData)->clrSet = nil;
- }
-
- /* Dispose of the Pentable if it was allocated */
- if ((*hImageData)->hPenTable != nil)
- {
- DisposHandle((Handle) (*hImageData)->hPenTable);
- (*hImageData)->hPenTable = nil;
- }
-
- /* Dispose of the Device Transform if it was allocated */
- if ((*hImageData)->devTransform != nil)
- {
- GXDisposeTransform((*hImageData)->devTransform);
- (*hImageData)->devTransform = nil;
- }
-
- anErr = Forward_GXCloseConnection();
-
- return(anErr);
-
- }
- /* SD_CloseConnection */
-
-
- /* ========================= VECTOR SPECIFIC MESSAGE OVERRIDE ROUTINES ========================= */
-
- /* ======= SD_PackageData =======
-
- The PackageData message is issued by the Vector IE to signal that the specific driver should
- package the Graphics shape, shapeToDraw, in HPGL commands so it will be drawn. The routine should
- only ever receive line, rectangle, and non-filled polygon shapes from the Vector IE. Anything
- else is an error. The penIndex specifies which pen in the carousel to use for drawing. If
- it's different than the last pen used to draw, HPGL commands are generated to select the target
- pen.
- */
- OSErr SD_PackageData( // (out) error code
- gxShape shapeToDraw, // (in) Graphics shape to be drawn
- long penIndex) // (in) index in the carousel of the pen to use for drawing
- {
- // #pragma unused (penIndex)
-
- OSErr anErr = noErr;
- gxShapeAttribute theAttributes;
- gxVectorImageDataHdl hImageData;
- gxMapping theMapping;
- Fixed spenWidth;
- gxColor clr;
- short n;
- Str255 theStr;
-
- hImageData = gGlobals.hImageData;
-
- /* Create a temporary mapping that will scale the shape's points to the resolution of the device */
- {
- Fixed scaleFactor;
-
- scaleFactor = FixDiv((*hImageData)->devRes, ff(72));
-
- ResetMapping(&theMapping);
- ScaleMapping(&theMapping, scaleFactor, scaleFactor, 0, 0);
- }
-
- /* Make sure the shape is accessible to us by setting the directShape attribute. This */
- /* ensures we can access the shape's structure without it disappearing on us. */
- theAttributes = GXGetShapeAttributes(shapeToDraw);
- GXSetShapeAttributes(shapeToDraw, theAttributes | gxDirectShape);
-
- /* Lock the shape so it doesn't move while we access its structure */
- GXLockShape(shapeToDraw);
-
- /* set the pen thickness and the pen color */
- spenWidth = GXGetShapePen(shapeToDraw);
- if (spenWidth != 0)
- /* convert shape thickness in mm */
- spenWidth = FixedDivide(spenWidth, ff(40)); // 1016 dpi ==> 40 plotterpoints per mm.
- else
- spenWidth = FixedDivide(ff(25), ff(1000));
- if (gGlobals.penWidth != spenWidth)
- {
- // DebugStr("\p setting pen width.. ");
- GetIndString(theStr, kHPXLCmndStringsID, kSetPenWidthIdx);
- theStr[theStr[0]+1] = 0;
- n = sprintf(gGlobals.tempBuffer, (char *) &theStr[1], Fix2X(spenWidth));
- anErr = MyDumpBuffer( n);
-
- if (anErr != noErr)
- return(anErr);
- gGlobals.penWidth = spenWidth;
- }
-
- GXGetShapeColor(shapeToDraw, &clr);
- GetIndString(theStr, kHPXLCmndStringsID, kSetPenColorIdx);
- theStr[theStr[0]+1] = 0;
- n = sprintf(gGlobals.tempBuffer, (char *) &theStr[1], 1, clr.element.rgb.red >> 1,
- clr.element.rgb.green >> 1,
- clr.element.rgb.blue >> 1);
- anErr = MyDumpBuffer( n);
- if (anErr != noErr)
- return(anErr);
-
- switch ( GXGetShapeType(shapeToDraw) )
- {
- case gxLineType:
- anErr = PlotLine(shapeToDraw, theMapping);
- if (anErr != noErr) goto CantSendPlotLineCmnd;
- break;
-
- case gxRectangleType:
- anErr = PlotRectangle(shapeToDraw, theMapping);
- if (anErr != noErr) goto CantSendPlotRectCmnd;
- break;
-
- case gxPolygonType:
- anErr = PlotPolygon(shapeToDraw, theMapping);
- if (anErr != noErr) goto CantSendPlotPolyCmnd;
- break;
-
- default:
- break;// Not expecting any other shape types from the Vector IE
- }
-
- /* Unlock the shape so it can move again */
- GXUnlockShape(shapeToDraw);
-
- /* Restore the shape's attributes */
- GXSetShapeAttributes(shapeToDraw, theAttributes);
-
- return(anErr);
-
- /******* Cleanup *******/
-
- CantSendPlotPolyCmnd:
- CantSendPlotRectCmnd:
- CantSendPlotLineCmnd:
- CantSendSwitchPensCmnd:
- GXUnlockShape(shapeToDraw);
- GXSetShapeAttributes(shapeToDraw, theAttributes);
-
- return(anErr);
- }
- /* SD_PackageData */
-
- /* following stubs are to avoid errors in linking the driver. sprintf is allowed only for
- MPW tools and stand alone apps */
-
- size_t fwrite (const void *ptr, size_t size, size_t nmemb, FILE *stream)
- {
- DebugStr("\p in fwrite");
- return(0);
- }
-
- int _flsbuf(unsigned char aChar, FILE *stream)
- {
- DebugStr("\p in _flsbuf");
- }
-
-